﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.CBO.FA.CBO_FA_Enum;
using UFIDA.U9.CBO.FA.FA_AssetCategoryBE;
using UFIDA.U9.CBO.FA.FA_AssetOwnerRelation;
using UFIDA.U9.CBO.FA.FA_UseStateBE;
using UFIDA.U9.CBO.FI.FA;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.HR.Operator;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.FA.FA_AssetCardBE;
using UFIDA.U9.FA.FA_AssetCardBP;
using UFIDA.U9.FA.FA_AssetCardDocTypeBE;
using UFIDA.U9.FA.FA_AssetTypeBE;
using UFIDA.U9.FA.FA_DepreciationBookBE;
using UFIDA.U9.FA.FA_Enum;
using UFIDA.U9.FA.FA_Location;
using UFIDA.U9.InvTrans.InvTrans;
using UFIDA.U9.PM.Rcv;
using UFSoft.UBF.Business;
using UFSoft.UBF.Execution.WorkManagers;

namespace ufida.u9.ait.openapi
{
    internal class AssertCardBase
    {
        /// <summary>
        /// 资产卡片提交
        /// </summary>
        /// <param name="doc">资产卡片实体</param>
        /// <returns>资产卡片实体</returns>
        public static AssetCard CommitDoc(AssetCard doc)
        {
            doc = doc.Key.GetEntity();
            if (doc.Statues != AssetCardStatues.FAOpen)
                throw new Exception($"单号:[{doc.DocNo}]不为开立");
            
            //启用事务+调用BP,会导致接口卡死
            //原因可能是在服务中启用事务,在BP中又启用事务,两次事务冲突导致
            //AssetCardPost bp = new AssetCardPost();
            //bp.DocList = new List<UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO>()
            //{
            //    new UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO()
            //    {
            //        AssetCard=doc.Key,
            //        SysVersion=doc.SysVersion,
            //    }
            //};
            //UFIDA.U9.FA.FA_PropertyType.FABPReturnDTO fABPReturnDTO = bp.Do();

            //查看BP源码
            using(ISession session = Session.Open())
            {
                doc.Post();
                session.Commit();
            }

            return doc;
        }

        public static AssetCard UnApproveDoc(AssetCard doc)
        {
            if (doc.Statues != AssetCardStatues.Approved)
                throw new Exception($"单号:[{doc.DocNo}]不为审核");

            AssetCardUnApproved bp = new AssetCardUnApproved();
            bp.DocList = new List<UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO>()
            {
                new UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO()
                {
                    AssetCard=doc.Key,
                    SysVersion=doc.SysVersion,
                }
            };
            UFIDA.U9.FA.FA_PropertyType.FABPReturnDTO fABPReturnDTO = bp.Do();

            return doc;
        }
        /// <summary>
        /// 资产卡片审核
        /// </summary>
        /// <param name="doc">资产卡片实体</param>
        /// <returns>资产卡片实体</returns>
        public static AssetCard ApproveDoc(AssetCard doc)
        {
            doc = doc.Key.GetEntity();
            if (doc.Statues == AssetCardStatues.Approved)
                throw new Exception($"单号:[{doc.DocNo}]已经审核");

            //AssetCardApprove bp = new AssetCardApprove();
            //bp.DocList = new List<UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO>()
            //{
            //    new UFIDA.U9.FA.FA_AssetCardBP.AssetCardDTO()
            //    {
            //        AssetCard=doc.Key,
            //        SysVersion=doc.SysVersion,
            //    }
            //};
            //UFIDA.U9.FA.FA_PropertyType.FABPReturnDTO fABPReturnDTO = bp.Do();

            //查看BP源码
            using (ISession session = Session.Open())
            {
                doc.Approve();
                session.Commit();
            }

            return doc;
        }
        /// <summary>
        /// 创建资产卡片
        /// </summary>
        /// <param name="dto">DTO数据</param>
        /// <returns>资产卡片实体</returns>
        public static AssetCard CreateDoc(AssertCardAITDTOData dto)
        {
            RcvLineDispense srcline;
            AssetCard doc;

            using (ISession session = Session.Open())
            {
                //创建 资产卡片 头
                doc = CreateHead(dto, out srcline);
                //创建 资产卡片来源单据信息
                CreateSource(dto, srcline, doc);
                //创建 资产卡片财务信息
                CreateAssetAccountInfor(dto, srcline, doc);
                //创建 资产卡片实物管理信息
                CreateAssetTag(dto, srcline, doc);
                //创建	资产关联成本行
                CreateAssetCostLine(srcline, doc);

                session.Commit();
            }

            //更新收货单信息
            RCVBase.CardUpdateRcv(srcline, dto.Qty);

            return doc;
        }

        //创建 资产卡片 头
        private static AssetCard CreateHead(AssertCardAITDTOData dto, out RcvLineDispense srcline)
        {
            srcline = null;
            if (dto.SourceDoc != null)
            {
                AssertCardSourceDocAITDTOData srcdto = dto.SourceDoc;
                string path = $"DispenseLineNo={srcdto.SourceDocLineDetailNo} and RcvLine.DocLineNo={srcdto.SourceDocLineNo} and RcvLine.Receivement.DocNo='{srcdto.SourceDocCode}'";
                srcline = RcvLineDispense.Finder.Find(path);
                if (srcline == null) throw new Exception($"查询收货单分发子表失败,path:[{path}]");
            }

            AssetCard doc = AssetCard.Create();
            //单据类型
            if (dto.DocumentType == null) throw new Exception("单据类型 必填");
            doc.DocumentType = EntityUtils.GetEntityByCode<AssetCardDocType>(dto.DocumentType.Code);

            //日期
            if (string.IsNullOrEmpty(dto.BusinessDate)) throw new Exception("单据日期 必填");
            doc.BusinessDate = DateTime.Parse(dto.BusinessDate);
            if (string.IsNullOrEmpty(dto.StartDate))
            {
                doc.StartDate = doc.BusinessDate;
            }
            else
            {
                doc.StartDate = DateTime.Parse(dto.StartDate);
            }

            //组织/部门/责任人
            doc.Org = Context.LoginOrg;
            doc.OwnerOrg = doc.Org;
            if (dto.OwnerDept == null) throw new Exception("管理部门 必填");
            doc.OwnerDept = EntityUtils.GetEntityByCode<Department>(dto.OwnerDept.Code);//管理部门
            if (dto.AuditDept == null) throw new Exception("核算部门 必填");
            doc.AuditDept = EntityUtils.GetEntityByCode<Department>(dto.AuditDept.Code);//核算部门
            if (dto.Owner != null)
            {
                doc.Owner=EntityUtils.GetEntityByCode<Operators>(dto.Owner.Code);//责任人
            }
            //物料
            if (dto.Item == null || string.IsNullOrEmpty(dto.Item.Code))
                throw new Exception("Item 为空");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(dto.Item.Code);
            if (srcline != null)
            {
                if (srcline.RcvLine.ItemInfo.ItemCode != item.Code)
                    throw new Exception($"来源单据料号[{srcline.RcvLine.ItemInfo.ItemCode}]与传入料号[{item.Code}]不同");
            }
            doc.Item = item;//资产
            doc.ItemCode = item.Code;//资产编号
            doc.AssetName = item.Name;//资产名称
            doc.UOM = item.InventoryUOM;
            if(!string.IsNullOrEmpty(dto.ItemCode))
                doc.ItemCode = dto.ItemCode;//资产编号
            if(!string.IsNullOrEmpty(dto.AssetName))
                doc.AssetName = dto.AssetName;//资产名称

            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }

            //其它
            if (dto.Qty == 0) throw new Exception("数量 必填");
            doc.Qty = dto.Qty;
            doc.AssetDescription = dto.AssetDescription;
            //doc.AssetType = EntityUtils.GetEntityByCode<AssetType>("1");//资产性态
            //资产货主关系
            doc.AssetOwnerRelation = EntityUtils.GetAssetOwnerRelation();
            if (dto.AssetCategory == null) throw new Exception("资产类别 必填");
            doc.AssetCategory = EntityUtils.GetEntityByCode<AssetCategory>(dto.AssetCategory.Code);//资产类别
            doc.Project=EntityUtils.GetEntityByCode<Project>(dto.Project);//项目

            return doc;
        }

        //创建 资产卡片实物管理信息
        private static void CreateAssetTag(AssertCardAITDTOData dto, RcvLineDispense srcline, AssetCard doc)
        {

            int num = dto.Qty;
            for (int i = 1; i <= num; i++)
            {
                AssetTag tag = AssetTag.Create(doc);
                tag.Style = doc.Item.SPECS;

                tag.LineNum = i * 10;
                tag.Code = "自动编号";
                if (dto.AssetLocation == null) throw new Exception("资产地址 必填");
                tag.AssetLocation = EntityUtils.GetEntityByCode<FA_Location>(dto.AssetLocation.Code);

                if (srcline != null)
                {
                    tag.SourceDocLineSysVersion = srcline.SysVersion;
                    tag.SourceDocLine = srcline.ID;
                }

                if (doc.SourceDoc != null && doc.SourceDoc.Count > 0)
                {
                    //更新 来源信息中的实物字段
                    SourceDoc sourceDoc = doc.SourceDoc[0];
                    sourceDoc.AssetTag = tag;
                }

                //实体扩展信息
                if (dto.TagDescFlexField != null)
                {
                    tag.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                    DTOUtils.DTOPropCopy(dto.TagDescFlexField, tag.DescFlexField);
                }


                //创建 资产卡片实物管理资产使用信息
                CreateAssetTagUsageInformation(dto, srcline, tag);
            }
        }

        //创建 资产卡片来源单据信息
        private static void CreateSource(AssertCardAITDTOData dto, RcvLineDispense srcline, AssetCard doc)
        {
            if (srcline == null) return;

            RcvLine rcvline = srcline.RcvLine;
            Receivement rcv = rcvline.Receivement;

            SourceDoc srcdoc = SourceDoc.Create(doc);
            srcdoc.UOM = doc.UOM;
            srcdoc.SourceOrg = doc.Org;
            srcdoc.SourceDocSysversion = rcv.SysVersion;
            srcdoc.SourceDocLineSysversion = rcvline.SysVersion;
            srcdoc.SourceDocLineNo = rcvline.DocLineNo;
            srcdoc.SourceDocLineID = rcvline.ID;
            srcdoc.SourceDocLineDetailSysversion = srcline.SysVersion;
            srcdoc.SourceDocLineDetailNo=srcline.DispenseLineNo;
            srcdoc.SourceDocLineDetailID=srcline.ID;
            srcdoc.SourceDocID = rcv.ID;
            srcdoc.SourceDocCode = rcv.DocNo;
            srcdoc.Qty=dto.Qty;
            srcdoc.LineNum = 10;
            //srcdoc.AssetTag= //资产标签 这个应该是 实物信息 回写
        }



        //创建 资产卡片财务信息
        private static void CreateAssetAccountInfor(AssertCardAITDTOData dto, RcvLineDispense srcline, AssetCard doc)
        {
            if (srcline == null && dto.AssetAccountInfor == null)
                throw new Exception("来源信息或财务信息 必填一个");

            //查询 资产类别SOB数据
            string path= $"SOB={EntityUtils.getSetofBooks().ID} and AssetCategory={doc.AssetCategory.ID}";
            SOBForAssetCategory sobcate = EntityUtils.GetEntityByPath<SOBForAssetCategory>(path);
            //创建实体
            AssetCardAccountInformation accinfo = AssetCardAccountInformation.Create(doc);
            accinfo.UseStateByCreated = EntityUtils.GetEntityByCode<UseState>("01");//使用状况
            accinfo.UseState = accinfo.UseStateByCreated;
            
            accinfo.IsDepreciateByCreated = sobcate.IsDepreciate;//计提折旧
            accinfo.IsDepreciate = accinfo.IsDepreciate;
            accinfo.DepreciationMethodByCreated = sobcate.DefaultDepreciationMethod;//折旧方法
            accinfo.DepreciationMethod = accinfo.DepreciationMethodByCreated;
            accinfo.UsedLifeYearByCreated = sobcate.EstimatedUsefulLifeYear;//使用年限
            accinfo.UsedLifeYear = accinfo.UsedLifeYearByCreated;
            accinfo.UsedLifePeriodByCreated = sobcate.EstimatedUsefulLifePeriod;//使用期间数
            accinfo.UsedLifePeriod = accinfo.UsedLifePeriodByCreated;
            accinfo.SalvageTypeByCreated = sobcate.SalvageValueType;//	残值类型
            accinfo.SalvageType = accinfo.SalvageTypeByCreated;
            accinfo.SalvageRatioByCreated = sobcate.SalvageValueRatio;//残值率
            accinfo.SalvageRatio = accinfo.SalvageRatioByCreated;

            accinfo.UOMByCreated = doc.UOM;
            accinfo.SOB = EntityUtils.getSetofBooks();
            
            accinfo.PrevBusiness = CurrentBusinessEnum.FANormal;//上次业务
            accinfo.CurrentBusiness = CurrentBusinessEnum.FANormal;//当前业务
            accinfo.LineNum = 10;
            accinfo.DpBook = EntityUtils.GetDpBook();//折旧账簿
            accinfo.Currency = EntityUtils.GetEntityByCode<Currency>("C001");
            accinfo.CreateDPPeriod = EntityUtils.GetDpPeriod(doc.BusinessDate);//建账折旧账簿期间
            accinfo.CreateDate = doc.BusinessDate;//建账日期
            accinfo.AssetCategorySOB = doc.AssetCategory.GetSOBForAssetCategory(accinfo.SOB);// 资产类别SOB
            accinfo.AlreadyUsedPeriodsByCreated = 1;//累计使用期间数
            accinfo.AccumulateUsedPeriods = 1;//累计使用期间数

            //金额处理
            if (srcline != null)
            {
                accinfo.TaxByCreated = srcline.UsedTaxAC;//税金
                accinfo.Tax = accinfo.TaxByCreated;
                accinfo.CostWithoutTaxByCreated = srcline.NetUsedMnyTC;//未税成本
                accinfo.CostWithoutTax = accinfo.CostWithoutTaxByCreated;
                accinfo.FeeByCreated = 0;//费用
                accinfo.Fee = accinfo.FeeByCreated;
            }
            else if(dto.AssetAccountInfor!=null)
            {
                accinfo.TaxByCreated = dto.AssetAccountInfor.TaxByCreated;//税金
                accinfo.Tax = accinfo.TaxByCreated;
                accinfo.CostWithoutTaxByCreated = dto.AssetAccountInfor.CostWithoutTaxByCreated;//未税成本
                accinfo.CostWithoutTax = accinfo.CostWithoutTaxByCreated;
                accinfo.FeeByCreated = dto.AssetAccountInfor.FeeByCreated;//费用
                accinfo.Fee = accinfo.FeeByCreated;
            }
            

            accinfo.RecoverableCostByCreated = accinfo.CostWithoutTax + accinfo.Fee;//可回收市值
            accinfo.RecoverableCost = accinfo.RecoverableCostByCreated;
            accinfo.OriginalValueByCreated = accinfo.CostWithoutTax + accinfo.Fee;//资产原值
            accinfo.OriginalValue = accinfo.OriginalValueByCreated;
            accinfo.NetValueByCreated = accinfo.CostWithoutTax + accinfo.Fee;//资产净值
            accinfo.NetValue = accinfo.NetValueByCreated;
            accinfo.EstimateSalvageValueByCreated = accinfo.OriginalValueByCreated * accinfo.SalvageRatio;//预估残值
            accinfo.EstimateSalvageValue = accinfo.EstimateSalvageValueByCreated;
        }

        //创建 资产卡片实物管理资产使用信息
        private static void CreateAssetTagUsageInformation(AssertCardAITDTOData dto, RcvLineDispense srcline, AssetTag tag)
        {
            
            AssetCard doc = tag.AssetCard;
            if (doc.AssetAccountInfor == null || doc.AssetAccountInfor.Count == 0)
                throw new Exception("AssetAccountInfor 为空,先创建 AssetAccountInfor");
            AssetCardAccountInformation accinfo = doc.AssetAccountInfor[0];
            AssetTagUsageInformation use = AssetTagUsageInformation.Create(accinfo);

            use.Percentage = 1;
            use.UsageOrg = doc.Org;
            use.FromDate = doc.BusinessDate;
            use.ToDate = doc.BusinessDate.AddYears(accinfo.UsedLifeYearByCreated);
            use.SetAssetTag(tag);
            use.AssetCard = tag.AssetCard;

            //项目
            use.Project = EntityUtils.GetEntityByCode<Project>(dto.Project);

            //使用部门/人员
            if (dto.UsageDept != null)
            {
                use.UsageDept=EntityUtils.GetEntityByCode<Department>(dto.UsageDept.Code);
            }
            else
            {
                use.UsageDept = doc.OwnerDept;
            }
            if (dto.UsagePrincipal != null)
            {
                use.UsagePrincipal = EntityUtils.GetEntityByCode<Operators>(dto.UsagePrincipal.Code) ;
            }
            

        }

        //创建	资产关联成本行
        private static void CreateAssetCostLine(RcvLineDispense srcline, AssetCard doc)
        {
            if (srcline == null) return;

            if (doc.AssetAccountInfor == null || doc.AssetAccountInfor.Count == 0)
                throw new Exception("AssetAccountInfor 为空,先创建 AssetAccountInfor");
            AssetCardAccountInformation accinfo = doc.AssetAccountInfor[0];
            AssetCostLine costline = AssetCostLine.Create(accinfo);

            if (doc.SourceDoc == null || doc.SourceDoc.Count == 0)
                throw new Exception("SourceDoc 为空,先创建 SourceDoc");
            costline.SourceDoc = doc.SourceDoc[0];
            costline.Tax = srcline.UsedTaxTC;
            costline.OriginalTax = srcline.UsedTaxTC;
            costline.OriginalCurrency = accinfo.Currency;
            costline.OriginalCostWithoutTax = accinfo.CostWithoutTaxByCreated;
            costline.FunctionalCurrency = accinfo.Currency;
            costline.ExchangeRate = 1;
            costline.CostWithoutTax = accinfo.CostWithoutTaxByCreated;
            costline.CostLineNo = 10;
            costline.AssetCard = doc;
        }
    }
}
